package com.example.previewvideo;

import androidx.appcompat.app.AppCompatActivity;

import android.Manifest;
import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageManager;
import android.graphics.SurfaceTexture;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCaptureSession;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CameraManager;
import android.hardware.camera2.CameraMetadata;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.params.StreamConfigurationMap;
import android.media.MediaRecorder;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.util.Size;
import android.view.Surface;
import android.view.TextureView;
import android.view.View;
import android.widget.ImageButton;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.core.app.ActivityCompat;

import com.blankj.utilcode.util.ActivityUtils;
import com.blankj.utilcode.util.AppUtils;
import com.blankj.utilcode.util.LogUtils;
import com.blankj.utilcode.util.Utils;
import com.example.demo.R;
import com.example.previewvideo.util.CameraUtils;
import com.example.previewvideo.util.VideoComposer;

import java.io.File;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;

public class Camera2VideoCaptureActivity extends AppCompatActivity {

    private static final String TAG = "Camera2VideoCaptureActivity";

    private static final int REQUEST_CAMERA_PERMISSION = 1;

    private CameraManager cameraManager;
    private String cameraId;
    private CameraDevice cameraDevice;
    private CameraCaptureSession captureSession;
    private Size previewSize;

    private MediaRecorder mediaRecorder;
    private boolean isRecording = false;

    private TextureView textureView;
    private ImageButton btnRecord;

    int desiredWidth = 1280;
    int desiredHeight = 720;

    int recordTime = 5 * 1000;//秒
    int fps = 30;
    private Handler handler;
    //1Mbps等于每秒传输1兆比特（即1,000,000比特
    //    int bitRate = 100 * 1000000;// 100 Mbps
    int bitRate = 5000 * 1000;//  Mbps


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_camera2videocapture);

        textureView = findViewById(R.id.textureView);

        btnRecord = findViewById(R.id.btnRecord);

        btnRecord.setOnClickListener(v -> {
            if (isRecording) {
                stopRecording();
            } else {
                startRecording();

            }
        });

        findViewById(R.id.btnRecordhb).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                startCompose();
            }
        });





        cameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
        textureView.setSurfaceTextureListener(surfaceTextureListener);
        handler = new Handler(Looper.getMainLooper());


        AppUtils.registerAppStatusChangedListener(new Utils.OnAppStatusChangedListener() {
            @Override
            public void onForeground(Activity activity) {

                LogUtils.i(TAG, "onForeground  ");

                isForeground = true;
            }

            @Override
            public void onBackground(Activity activity) {
                LogUtils.i(TAG, "onBackground  ");
            }
        });



    }



    private void startCompose() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                ArrayList videoList = new ArrayList<>();
                //待合成的2个视频文件
                videoList.add("/data/data/com.example.myapplication/cache/videoNameA/0.mp4");
                videoList.add("/data/data/com.example.myapplication/cache/videoNameA/1.mp4");
                videoList.add("/data/data/com.example.myapplication/cache/videoNameA/2.mp4");
                videoList.add("/data/data/com.example.myapplication/cache/videoNameA/3.mp4");
                videoList.add("/data/data/com.example.myapplication/cache/videoNameA/4.mp4");
                videoList.add("/data/data/com.example.myapplication/cache/videoNameA/5.mp4");
                VideoComposer composer = new VideoComposer(videoList, "/data/data/com.example.myapplication/cache/videoNameA/out.mp4");
                final boolean result = composer.joinVideo();

                btnRecord.post(new Runnable() {
                    @Override
                    public void run() {
                        Toast.makeText(Camera2VideoCaptureActivity.this, "合成结果 " + result, Toast.LENGTH_LONG);
                    }
                });
                Log.i(TAG, "compose result: " + result);
            }
        }).start();
    }

    boolean isForeground = false;

    private TextureView.SurfaceTextureListener surfaceTextureListener = new TextureView.SurfaceTextureListener() {
        @Override
        public void onSurfaceTextureAvailable(@NonNull SurfaceTexture surface, int width, int height) {
            openCamera();
        }

        @Override
        public void onSurfaceTextureSizeChanged(@NonNull SurfaceTexture surface, int width, int height) {
            // Ignored, Camera does not support resizing
        }

        @Override
        public boolean onSurfaceTextureDestroyed(@NonNull SurfaceTexture surface) {
            return false;
        }

        @Override
        public void onSurfaceTextureUpdated(@NonNull SurfaceTexture surface) {
            // Invoked every time there's a new Camera preview frame
        }
    };

    private void openCamera() {
        try {
            cameraId = cameraManager.getCameraIdList()[0]; // Use the first camera available

            if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
                ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, REQUEST_CAMERA_PERMISSION);
                return;
            }
            setUpCameraOutputs();
            cameraManager.openCamera(cameraId, new CameraDevice.StateCallback() {
                @Override
                public void onOpened(@NonNull CameraDevice camera) {
                    cameraDevice = camera;

                    LogUtils.i(TAG, "cameraManager onOpened  ");

                    createCameraPreview();
                }

                @Override
                public void onDisconnected(@NonNull CameraDevice camera) {

                    LogUtils.i(TAG, "cameraManager onDisconnected  ");
                    if (cameraDevice != null) {
                        cameraDevice.close();
                        cameraDevice = null;
                    }
                }

                @Override
                public void onError(@NonNull CameraDevice camera, int error) {
                    LogUtils.i(TAG, "cameraManager onError  " + error);
                    if (cameraDevice != null) {
                        cameraDevice.close();
                        cameraDevice = null;
                    }
                }
            }, null);
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
    }

    private void createCameraPreview() {
        try {
            SurfaceTexture texture = textureView.getSurfaceTexture();


//            texture.setDefaultBufferSize(previewSize.getWidth(), previewSize.getHeight());
            texture.setDefaultBufferSize(1280, 720);

            Surface surface = new Surface(texture);
            LogUtils.i(TAG, "createCameraPreview cameraDevice  " + cameraDevice+" previewSize.getWidth(): "+previewSize.getWidth()+" previewSize.getHeight(): "+previewSize.getHeight());
            final CaptureRequest.Builder previewRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
            previewRequestBuilder.addTarget(surface);

            cameraDevice.createCaptureSession(Collections.singletonList(surface), new CameraCaptureSession.StateCallback() {
                @Override
                public void onConfigured(@NonNull CameraCaptureSession session) {
                    LogUtils.i(TAG, "createCaptureSession onConfigured  ");
                    captureSession = session;
                    try {
                        previewRequestBuilder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO);
                        captureSession.setRepeatingRequest(previewRequestBuilder.build(), null, null);
                    } catch (CameraAccessException e) {
                        e.printStackTrace();
                    }
                }

                @Override
                public void onConfigureFailed(@NonNull CameraCaptureSession session) {
                    LogUtils.i(TAG, "createCaptureSession onConfigureFailed  ");
                    Toast.makeText(Camera2VideoCaptureActivity.this, "Failed to create camera preview", Toast.LENGTH_SHORT).show();
                }
            }, null);
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
    }

    int count = 0;

    private void startRecording() {
        try {
            closePreviewSession();

            int vb = 7;  // 视频码流Mb

            mediaRecorder = new MediaRecorder();

            // 设置要用于录制的音频源。
            mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
            // 设置要用于录制的视频源。
            mediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
            // 设置录制期间生成的输出文件的格式。
            mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);//Mp4 H264   PS流
//            mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_2_TS);//  TS流

            //设置录制视频编码比特率 10000000
            mediaRecorder.setVideoEncodingBitRate(fps*vb*1024*1024);

            mediaRecorder.setAudioEncodingBitRate(64*1024);

            // 设置要捕获的视频的帧速率。
            mediaRecorder.setVideoFrameRate(fps);
//            mediaRecorder.setVideoSize(previewSize.getWidth(), previewSize.getHeight());
            mediaRecorder.setVideoSize(1280, 720);
            // 设置要用于录制的视频编码器。
            mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
            // 设置要用于录制的音频编码器。
            mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
            String string = getOutputMediaFile().toString();
            LogUtils.i(TAG + " setOutputFile:" + string);

            mediaRecorder.setOutputFile(string);

//            mediaRecorder.setOrientationHint(getOrientation());
            mediaRecorder.setOrientationHint(180);

           int sSize =  (fps*vb*1024*1024 + 64*1024)/8;

            LogUtils.i(TAG + " sSize  :" + sSize/1024+" VideoBitRate: "+fps*vb*1024*1024+" AudioBitRate: "+64*1024+" fps: "+fps);

//            mediaRecorder.setMaxFileSize(1024*1024*5);
            mediaRecorder.setMaxDuration(10 * 1000);

            mediaRecorder.setOnInfoListener(new MediaRecorder.OnInfoListener() {
                @Override
                public void onInfo(MediaRecorder mediaRecorder, int i, int i1) {
                    LogUtils.i(TAG + " setOnInfoListener i :" + i);
//                    if (i == MediaRecorder.MEDIA_RECORDER_INFO_MAX_FILESIZE_APPROACHING) {
//                        String string = getOutputMediaFile().toString();
//                        LogUtils.i(TAG + " setOnInfoListener getOutputMediaFile  :" + string);
//                        try {
//                            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
//                                mediaRecorder.setNextOutputFile(new File(string));
//                            }
//                        } catch (Exception e) {
//                        }
//                    }
                    if (i == MediaRecorder.MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED) {

                        LogUtils.i(TAG + " setOnInfoListener getOutputMediaFile  :" + new File(getOutputMediaFile().toString()).getPath().length());

                        count++;
                        String string =getOutputMediaFile().toString() ;
                        try {
                             if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                                mediaRecorder.setNextOutputFile(new File(string));
                            }
                        } catch (Exception e) {
                        }
                    }

                }
            });

            mediaRecorder.setOnErrorListener(new MediaRecorder.OnErrorListener() {
                @Override
                public void onError(MediaRecorder mediaRecorder, int i, int i1) {
                    LogUtils.i(TAG + " setOnErrorListener i :" + i);
                }
            });




//            handler.postDelayed(new Runnable() {
//                @Override
//                public void run() {
//
//
//                    runOnUiThread(new Runnable() {
//                        @Override
//                        public void run() {
//                            count++;
//                            String string = getOutputMediaFile().toString();
////                            LogUtils.i(TAG + " setOnInfoListener getOutputMediaFile  :" + string);
//                            LogUtils.i(TAG + " setOnInfoListener stopRecording count :" + count);
//
//                            stopRecording();
//
////                                mediaRecorder.reset();//通过返回setAudioSource（）步骤，可以重用该对象
//                            startRecording();
//                        }
//                    });
//
//
//
//                }
//            }, recordTime);

            try {
                mediaRecorder.prepare();
            } catch (Exception e) {
                e.printStackTrace();
                return;
            }

            SurfaceTexture texture = textureView.getSurfaceTexture();
//            texture.setDefaultBufferSize(previewSize.getWidth(), previewSize.getHeight());
            texture.setDefaultBufferSize(1280, 720);

            Surface surface = new Surface(texture);

            CaptureRequest.Builder captureBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_RECORD);
            captureBuilder.addTarget(surface);
            captureBuilder.addTarget(mediaRecorder.getSurface());

            List<Surface> surfaces = new ArrayList<>();
            surfaces.add(surface);
            surfaces.add(mediaRecorder.getSurface());

            LogUtils.i(TAG + " setOnInfoListener stopRecording 111 count :" + count);
            cameraDevice.createCaptureSession(surfaces, new CameraCaptureSession.StateCallback() {
                @Override
                public void onConfigured(@NonNull CameraCaptureSession session) {
                    captureSession = session;
                    try {
                        LogUtils.i(TAG + " setOnInfoListener stopRecording 222 count :" + count);
                        captureSession.setRepeatingRequest(captureBuilder.build(), null, null);
                        mediaRecorder.start();
                        LogUtils.i(TAG + " setOnInfoListener stopRecording 333 count :" + count);

                        isRecording = true;
                        btnRecord.setImageResource(R.drawable.ic_launcher_background);
                        Toast.makeText(Camera2VideoCaptureActivity.this, "Recording started", Toast.LENGTH_SHORT).show();
                        LogUtils.i(TAG, "Recording started");



                    } catch (Exception e) {
                        LogUtils.i(TAG, "startRecording onConfigured Exception: " + e.getMessage());

                        e.printStackTrace();
                    }
                }

                @Override
                public void onConfigureFailed(@NonNull CameraCaptureSession session) {
                    Toast.makeText(Camera2VideoCaptureActivity.this, "Failed to create capture session", Toast.LENGTH_SHORT).show();
                }
            }, null);
        } catch (Exception e) {
            LogUtils.i(TAG, "startRecording Exception: " + e.getMessage());
            e.printStackTrace();
        }
    }

    private void stopRecording() {
        if (isRecording) {
            isRecording = false;
            mediaRecorder.stop();
            mediaRecorder.reset();//通过返回setAudioSource（）步骤，可以重用该对象
            mediaRecorder.release();// 现在该对象无法重用
            mediaRecorder = null;
            btnRecord.setImageResource(R.drawable.ic_launcher_background);
            Toast.makeText(Camera2VideoCaptureActivity.this, "Recording saved: " + getOutputMediaFile().getPath(), Toast.LENGTH_SHORT).show();
            LogUtils.i(TAG, "Recording saved", getOutputMediaFile().getPath());

            handler.removeCallbacksAndMessages(null);
//            createCameraPreview();

//            startRecording();
        }
    }

    private void closePreviewSession() {
        if (captureSession != null) {
            captureSession.close();
            captureSession = null;
        }
    }

    @Override
    protected void onStop() {
        super.onStop();
//        closeCamera();
    }

    private void closeCamera() {
        if (cameraDevice != null) {
            cameraDevice.close();
            cameraDevice = null;
        }
    }

    private File getOutputMediaFile() {
        String directoryPath = getCacheDir().getAbsolutePath() + "/videoNameA/";
        File mediaStorageDir = new File(directoryPath);
        if (!mediaStorageDir.exists()) {
            if (!mediaStorageDir.mkdirs()) {
                return null;
            }
        }

        String timestamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
        return new File(mediaStorageDir.getPath() + "/"+ count + ".mp4");
    }

    private void setUpCameraOutputs() {
        try {
            CameraCharacteristics characteristics = cameraManager.getCameraCharacteristics(cameraId);
            StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);

            // 获取支持的预览尺寸列表
            Size[] outputSizes = map.getOutputSizes(SurfaceTexture.class);

            // 选择最合适的预览尺寸，这里可以根据需要进行适当的逻辑处理
            previewSize = chooseOptimalSize(outputSizes, desiredWidth, desiredHeight);
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
    }

    private Size chooseOptimalSize(Size[] choices, int width, int height) {
        List<Size> bigEnough = new ArrayList<>();
        for (Size option : choices) {
            if (option.getWidth() >= width && option.getHeight() >= height) {
                bigEnough.add(option);
            }
        }
        if (bigEnough.size() > 0) {
            return Collections.min(bigEnough, new Comparator<Size>() {
                @Override
                public int compare(Size lhs, Size rhs) {
                    return Long.signum((long) lhs.getWidth() * lhs.getHeight() - (long) rhs.getWidth() * rhs.getHeight());
                }
            });
        } else {
            return choices[0]; // 如果没有合适的尺寸，返回默认的第一个尺寸
        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        LogUtils.i(TAG, "onForeground  " + isForeground);

        if (isForeground) {

//            openCamera();

        }


        boolean isCameraUsed = CameraUtils.isCameraInUse();
        if (isCameraUsed) {
            // 相机正在被使用
            // 执行相应的操作，例如禁用其他应用程序对相机的访问权限

            LogUtils.i(TAG, "相机是否被使用", "相机正在被使用");
        } else {
            // 相机未被使用
            // 执行相应的操作，例如打开相机进行拍照
            LogUtils.i(TAG, "相机是否被使用", "相机未被使用");
        }
    }

    private int getOrientation() {
        // Get the current device orientation
        int rotation = getWindowManager().getDefaultDisplay().getRotation();
        int orientation = 0;
        switch (rotation) {
            case Surface.ROTATION_0:
                orientation = 90;
                break;
            case Surface.ROTATION_90:
                orientation = 0;
                break;
            case Surface.ROTATION_180:
                orientation = 270;
                break;
            case Surface.ROTATION_270:
                orientation = 180;
                break;
        }
        return orientation;
    }


//
//    @Override
//    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
//        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
//        if (requestCode == 1) {
//            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
//                // 权限被授予
//                WifiUtils.getConnectedWifiInfo(this);
//            } else {
//                // 权限被拒绝
//                Toast.makeText(this, "Permission denied", Toast.LENGTH_SHORT).show();
//            }
//        }
//    }


}

